home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dr. Windows 3
/
dr win3.zip
/
dr win3
/
PROGRAMR
/
OLE2BOOK.ZIP
/
CHAP08.ZIP
/
CHAP08
/
PATRON
/
TENANT.CPP
< prev
Wrap
C/C++ Source or Header
|
1993-06-07
|
22KB
|
940 lines
/*
* TENANT.CPP
* Modifications for Chapter 8: None
*
* Implementation of the CTentant class which holds information
* for a single object on a page. It maintains position, references
* to data, and a storage.
*
* Copyright (c)1993 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Software Design Engineer
* Microsoft Systems Developer Relations
*
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/
#include "patron.h"
/*
* CTenant::CTenant
* CTenant::~CTenant
*
* Constructor Parameters:
* dwID DWORD identifier for this page.
* hWnd HWND of the pages window.
* pPG LPCPages to the parent structure.
*/
CTenant::CTenant(DWORD dwID, HWND hWnd, LPCPages pPG)
{
m_hWnd=hWnd;
m_dwID=dwID;
m_fInitialized=0;
m_pIStorage=NULL;
m_cOpens=0;
m_pObj=NULL;
m_pPG =pPG;
return;
}
CTenant::~CTenant(void)
{
#ifdef DEBUG
char szTemp[128];
if (0!=m_cOpens)
{
wsprintf(szTemp, "::~CTenant m_cOpens=%lu", m_cOpens);
MessageBox(m_hWnd, szTemp, "Assert", MB_OK);
}
#endif
if (NULL!=m_pObj)
{
//We know we only hold one reference from UCreate or FLoad
m_pObj->Release();
m_pObj=NULL;
}
return;
}
/*
* CTenant::GetID
*
* Return Value:
* DWORD dwID field in this tenant. This function is only here
* to avoid hiding inline implementations in pages.h
*/
DWORD CTenant::GetID(void)
{
return m_dwID;
}
/*
* CTenant::GetStorageName
*
* Parameters:
* pszName LPSTR to a buffer in which to store the storage name
* for this tenant.
*
* Return Value:
* UINT Number of characters stored.
*/
UINT CTenant::GetStorageName(LPSTR pszName)
{
return wsprintf(pszName, "Tenant %lu", m_dwID);
}
/*
* CTenant::UCreate
*
* Purpose:
* Creates a new tenant of the given CLSID, which can be either a
* static bitmap or metafile now (Chapter 7) and which may eventually
* be any OLE object.
*
* Parameters:
* tType TENANTTYPE to create, either a static metafile, bitmap,
* or some kind of OLE object (later chapters)
* This determined which OleCreate* call we use.
* pvType LPVOID providing the relevant pointer from which
* to create the tenant, depending on iType.
* pFE LPFORMATETC specifying the type of renderings to use.
* pptl LPPOINTL in which we can store offset coordinates.
* pszl LPSIZEL where this object should store its lometric extents.
* pIStorage LPSTORAGE of the page we live in. We have to
* create another storage under this for the tenant.
* ppo LPPATRONOBJECT containing placement data.
* dwData DWORD containing extra data, sensitive to iType.
*
* Return Value:
* UINT A UCREATE_* value depending on what we actually do.
*/
UINT CTenant::UCreate(TENANTTYPE tType, LPVOID pvType, LPFORMATETC pFE
, LPPOINTL pptl, LPSIZEL pszl, LPSTORAGE pIStorage
, LPPATRONOBJECT ppo, DWORD dwData)
{
HRESULT hr;
LPUNKNOWN pObj;
UINT uRet=UCREATE_GRAPHICONLY;
if (NULL==pvType || NULL==pIStorage)
return UCREATE_FAILED;
//Fail if this is called for an already living tenant.
if (m_fInitialized)
return UCREATE_FAILED;
m_fInitialized=TRUE;
//Create a new storage for this tenant.
if (!FOpen(pIStorage))
return UCREATE_FAILED;
/*
* Get the placement info if it's here. We either have a non-NULL
* LPPATRONOBJECT in ppo or we have to use default placement and
* retrieve the size from the object itself.
*/
pszl->cx=0;
pszl->cy=0;
if (NULL!=ppo)
{
*pFE=ppo->fe;
*pptl=ppo->ptl;
*pszl=ppo->szl; //Could be 0,0 in which case we ask object
uRet=UCREATE_PLACEDOBJECT;
}
hr=ResultFromScode(E_FAIL);
//Now create an object based specifically for the type.
switch (tType)
{
case TENANTTYPE_NULL:
break;
case TENANTTYPE_STATIC:
/*
* We could use OleCreateStaticFromData here which does
* pretty much what we're doing below. However, it does
* not allow us to control whether we paste a bitmap or
* a metafile--it uses metafile first, bitmap second. For
* this reason we'll use code developed in Chapter 6's
* FreeLoader to affect the paste.
*/
hr=CreateStatic((LPDATAOBJECT)pvType, pFE, &pObj);
break;
default:
break;
}
//If creation didn't work, get rid for the element FOpen created.
if (FAILED(hr))
{
Destroy(pIStorage);
return UCREATE_FAILED;
}
//Otherwise, store the object pointer and initialize the tenant
m_pObj=pObj;
m_fe=*pFE;
m_dwState=TENANTSTATE_DEFAULT;
//If we also saw PatronObjects on the clipboard, we have size already.
if (0==pszl->cx && 0==pszl->cy)
{
LPOLEOBJECT pIOleObject;
//Try to get the real size of the object, default to 2"*2"
SETSIZEL((*pszl), 2*LOMETRIC_PER_INCH, 2*LOMETRIC_PER_INCH);
hr=pObj->QueryInterface(IID_IOleObject, (LPVOID FAR *)&pIOleObject);
if (SUCCEEDED(hr))
{
SIZEL szl;
pIOleObject->GetExtent(pFE->dwAspect, &szl);
pIOleObject->Release();
//Convert HIMETRIC to our LOMETRIC mapping
SETSIZEL((*pszl), szl.cx/10, szl.cy/10);
}
}
return uRet;
}
/*
* CTenant::FLoad
*
* Purpose:
* Recreates the object living in this tenant in place of calling
* FCreate. This is used in loading as opposed to new creation.
*
* Parameters:
* pIStorage LPSTORAGE of the page we live in.
* pFE LPFORMATETC specifying the type of renderings to use.
* prcl LPRECTL where this object is positioned.
*
* Return Value:
* BOOL TRUE if successful, FALSE otherwise.
*/
BOOL CTenant::FLoad(LPSTORAGE pIStorage, LPFORMATETC pFE, LPRECTL prcl)
{
HRESULT hr;
LPUNKNOWN pObj;
if (NULL==pIStorage || NULL==pFE || NULL==prcl)
return FALSE;
//Fail if this is called for an already living tenant.
if (m_fInitialized)
return FALSE;
m_fInitialized=TRUE;
//Open the storage for this tenant.
if (!FOpen(pIStorage))
return FALSE;
hr=OleLoad(m_pIStorage, IID_IUnknown, NULL, (LPVOID FAR *)&pObj);
if (FAILED(hr))
{
Destroy(pIStorage);
return FALSE;
}
//Otherwise, store the object pointer and initialize the tenant
m_pObj=pObj;
m_fe=*pFE;
m_dwState=TENANTSTATE_DEFAULT;
RectSet(prcl, FALSE);
return TRUE;
}
/*
* CTenant::FOpen
*
* Purpose:
* Retrieves the IStorage associated with this tenant. The IStorage is
* owned by the tenant and thus the tenant always holds a reference count.
*
* If the storage is already open for this tenant, then this function will
* AddRef it; therefore the caller must always match an FOpen with a Close.
*
* Parameters:
* pIStorage LPSTORAGE above this tenant (which has its own storage).
*
* Return Value:
* BOOL TRUE if opening succeeds, FALSE otherwise.
*/
BOOL CTenant::FOpen(LPSTORAGE pIStorage)
{
HRESULT hr=NOERROR;
DWORD dwMode=STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
char szTemp[32];
if (NULL==m_pIStorage)
{
if (NULL==pIStorage